import type { MDCElement } from '@nuxtjs/mdc'
import { withBase } from 'ufo'
import { pascalCase } from 'scule'
import type { LLMsSection } from 'nuxt-llms'
import { toHast } from 'minimark/hast'
import type { MinimarkTree } from 'minimark'
import type { PageCollectionItemBase, SQLOperator } from '@nuxt/content'
import manifest from '#content/manifest'

export interface ContentLLMSCollectionSection extends LLMsSection {
  __nuxt_content_auto_generate?: boolean
  contentCollection?: string
  contentFilters?: Array<{
    field: string
    operator: SQLOperator
    value?: string
  }>
}

const linkProps = ['href', 'src', 'to']

const importExternalPackage = async (name: string) => await import(name)

export async function createDocumentGenerator() {
  const visit = await importExternalPackage('unist-util-visit').then(res => res.visit)
  const stringifyMarkdown = await importExternalPackage('@nuxtjs/mdc/runtime').then(res => res.stringifyMarkdown)

  return generateDocument

  async function generateDocument(doc: PageCollectionItemBase, options: { domain: string }) {
    const hastTree = refineDocumentBody(doc.body as unknown as MinimarkTree, options)
    let markdown = await stringifyMarkdown(hastTree, {})

    if (!markdown?.trim().startsWith('# ')) {
      const title = doc.title || doc.seo?.title || ''
      if (title) {
        markdown = `# ${title}\n\n${markdown}`
      }
    }
    return markdown
  }

  function refineDocumentBody(body: MinimarkTree, options: { domain: string }) {
    const hastTree = toHast(body)

    visit(hastTree, (node: MDCElement) => !!node.props?.to || !!node.props?.href || !!node.props?.src, (node: MDCElement) => {
      for (const prop of linkProps) {
        if (node.props?.[prop]) {
          node.props[prop] = withBase(node.props[prop], options.domain)
        }
      }
    })
    return hastTree
  }
}

export function prepareContentSections(sections: LLMsSection[]) {
  const contentSections = (sections as ContentLLMSCollectionSection[]).filter(section => section.contentCollection)
  if (contentSections.length) {
    // If there are already content sections, do not add auto generated sections
    return
  }
  const pageCollecitons = Object.keys(manifest).filter(c => (manifest[c] as { type: string }).type === 'page')

  const autoGeneratedSections = pageCollecitons.map(c => ({
    __nuxt_content_auto_generate: true,
    title: pascalCase(c),
    contentCollection: c,
    contentFilters: [
      {
        field: 'extension',
        operator: '=',
        value: 'md',
      },
    ],
  }))
  sections.push(...autoGeneratedSections)
}
